#define MAX_INSTRUCTION 50
#define MIN_FRAME_LEN 3
#define KEY_CODE_LEN 2
#define HOUSE_CODE_LEN 1

#define HOUSE_CODE 'A'
#define CONFIGURATION_KEY_CODE 'X'

//Cambios en pinguino
char tmpFrame[50];
byte leidos = 0;

/* Cambios para el correcto funcionamiento del usb en vez del puerto serie */
boolean usbReady(){
	char letra[1];
	if(getsUSBUSART(letra,1)>0){
		tmpFrame[leidos] = letra[0];
		if(letra[0] == '\n'){
			tmpFrame[leidos] = '\0';
			return TRUE;
		}
		leidos++;		
	}
	return FALSE;
}

void resetUsb(){
	leidos = 0;
}

/* end usb */

//This variables has to be implemented by the compiler
short int status[13];

//This function has to be implemented by the compiler
void beginDevices(){
	int i;
	for(i = 0; i < 14; i++){
		pinMode(i,OUTPUT);
		status[i] = 0;
		digitalWrite(i,LOW);
	}
}

//This function has to be implemented by the compiler
void elementHandler(short int keyCode, char * action){
	if(keyCode < 0 || keyCode > 13){
		#ifdef DEBUG
		//Serial.print("Error elemento no definido -> ");
		//Serial.println(keyCode);
		#endif
	}else{
		if(strcmp(action,"ON") == 0){
			status[keyCode] = 255;
			digitalWrite(keyCode,HIGH);
			#ifdef DEBUG
			//Serial.print("Enciende ");
			//Serial.println(keyCode);
			#endif
		}else if(strcmp(action,"OFF") == 0){
			status[keyCode] = 0;
			digitalWrite(keyCode,LOW);
			#ifdef DEBUG
			//Serial.print("Apaga ");
			//Serial.println(keyCode);			
			#endif
		}else if(strcmp(action,"STATUS") == 0){
			//Serial.println(status[keyCode]);
		}else if(strcmp(action,"ID") == 0){
			//Serial.println("Control luces v1.0");
		}
	}
}

void protocol(char houseCode, short int keyCode, char * action){
	switch(houseCode){
		case HOUSE_CODE:
			#ifdef DEBUG
			//Serial.println("Debe ejecutarse en local");
			#endif
			elementHandler(keyCode,action);
			break;
		case CONFIGURATION_KEY_CODE:	
			#ifdef DEBUG
			//Serial.println("Configuracion...");
			#endif
			break;
		default:
			#ifdef DEBUG
			//Serial.println("No es de aqui este paquete");
			#endif 
			break;
	}
}

void execute(char * frame){
	//check if the frame is valid
	short int len = strlen(frame);
	if(len > MIN_FRAME_LEN){
		char houseCode = frame[0];
		
		char * number = (char *) malloc(sizeof(char)*KEY_CODE_LEN);
		int j;
		for(j = 0; j < KEY_CODE_LEN; j++){
			number[j] = frame[j+HOUSE_CODE_LEN];
		}
		number[j] = '\0';
		short int keyCode = atoi(number);
		free(number);
		
		//The rest of the frame is the action.
		char * action = (char *) malloc(sizeof(char)*(MAX_INSTRUCTION-HOUSE_CODE_LEN-KEY_CODE_LEN));
		int i;
		j = 0;
		for(i = HOUSE_CODE_LEN + KEY_CODE_LEN; i < strlen(frame); i++){
			action[j] = frame[i];
			j++;
		}
		if (j < (MAX_INSTRUCTION-HOUSE_CODE_LEN-KEY_CODE_LEN))
			action[j] = '\0';
			
		#ifdef DEBUG
		//Serial.println(houseCode);
		//Serial.println(keyCode);
		//Serial.println(action);
		//Serial.println();
		#endif
		
		protocol(houseCode,keyCode,action);
		free(action);
	}
}


void run(){
	char * instruction = (char *)malloc(sizeof(char)*MAX_INSTRUCTION);
	while(!usbReady());
	byte l_s = sprintf(instruction,"%s",tmpFrame);
	CDC.print(instruction,l_s);
	execute(instruction);
	free(instruction);
	resetUsb();
}

void setup(){
	beginDevices();
}

void loop(){
	run();
}
